/**
 * 
 */
package tests;

import global.AttrType;
import global.Convert;
import global.RID;
import global.Size;
import global.SystemDefs;
import global.TID;
import heap.HFBufMgrException;
import heap.HFDiskMgrException;
import heap.HFException;
import heap.Heapfile;
import heap.InvalidSlotNumberException;
import heap.Scan;
import heap.Tuple;

import java.util.ArrayList;
import java.util.StringTokenizer;

import bitmap.BitMapFile;
import bitmap.InstantiateColumnarFile;
import bitmap.KeyClass;
import bitmap.StringKey;
import columnar.ColumnarFileInfo;
import columnar.Columnarfile;
import diskmgr.pcounter;

/**
 * @author gaurav
 *
 */
public class ColumnarBitmapEquiJoins {

	private static BitMapFile bmf = null, bmf1=null, resBf=null;	
	private static String columnDbName;
	private static String columnarFileName,columnarFileName1;
	private static ArrayList <String> columnNames=new ArrayList<String>();
	private static ArrayList <String> columnNames1=new ArrayList<String>();
	private static String valueConstraint;
	private static String numBuf;
	private static String columnName,columnName1;
	private static String operator;
	private static String columnValue, columnValue1;
	private static KeyClass value=null;
	private static int columnIndex=0,columnIndex1=0;
	private static int columnAbsoluteIndex=0,columnAbsoluteIndex1=0;
	private static Columnarfile f,s = null;
	private static AttrType[] types;
	private static int startRead = 0, startWrite = 0, intValue=0;
	private static String []colNames,colNames1;
	/**
	 * @param args
	 */
	
	public ColumnarBitmapEquiJoins(){}
	
	public ColumnarBitmapEquiJoins(String dbName, String colFile1, String colFile2, String valueConstr, String colval, String numBuffer, ArrayList <String> leftProjections, ArrayList <String> rightProjections)
	{
		columnDbName=dbName;
		columnarFileName=colFile1;
		columnarFileName1=colFile2;
		valueConstraint=valueConstr;
		columnValue=colval;
		columnValue1=columnValue;
		try  
	    {  
	       intValue=Integer.parseInt( columnValue );  
	       value=InstantiateColumnarFile.setKeyClass(value, 0, columnValue);
	    }  
	    catch( Exception e)  
	    {  
	    	value=InstantiateColumnarFile.setKeyClass(value, 1, columnValue);
	    }
		numBuf=numBuffer;
		for(String str: leftProjections)
			columnNames.add(str);
		for(String str: rightProjections)
			columnNames1.add(str);
	}
	
	public boolean isInteger( String input )  
	 {  
	    try  
	    {  
	       Integer.parseInt( input );  
	       return true;  
	    }  
	    catch( Exception e)  
	    {  
	       return false;  
	    }  
	} 
	
	public static void parseValue(String tempValue)
	{
		StringTokenizer st = new StringTokenizer(tempValue, ":");
		//System.out.println("0..."+tempValue);
		columnName=st.nextToken();
		//System.out.println("1..."+columnName);
		operator=st.nextToken();
		//System.out.println("1..."+operator);
		columnName1=st.nextToken();
		//System.out.println("1..."+columnName1);
		
		for(String str: colNames)
		{
			if(str.equalsIgnoreCase(columnName))
				break;
			columnIndex++;
		}

		for(String str: colNames1)
		{
			if(str.equalsIgnoreCase(columnName1))
				break;
			columnIndex1++;
		}

/*		columnValue=st.nextToken();
		//System.out.println("1..."+columnValue);
		columnValue1=columnValue;
		try  
	    {  
	       intValue=Integer.parseInt( columnValue );  
	       value=InstantiateColumnarFile.setKeyClass(value, 0, columnValue);
	    }  
	    catch( Exception e)  
	    {  
	    	value=InstantiateColumnarFile.setKeyClass(value, 1, columnValue);
	    }*/ 
	}


	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
	}
	
	public void join()
	{
		types = new AttrType[4];
		types[0] = new AttrType(AttrType.attrString);
		types[1] = new AttrType(AttrType.attrString);
		types[2] = new AttrType(AttrType.attrInteger);
		types[3] = new AttrType(AttrType.attrInteger);
		startRead = pcounter.rcounter;
		startWrite = pcounter.wcounter;

		SystemDefs sysdef = new SystemDefs(columnDbName,100000,Integer.parseInt(numBuf),"Clock");

		ColumnarFileInfo cInfo = new  ColumnarFileInfo(columnarFileName+".hdr");
		f=new Columnarfile(columnarFileName, 4, types);
		cInfo = f.getColumnarFileInfo(columnarFileName+".hdr");
		colNames = cInfo.getColumnNames();
		f.setColumnNames(colNames);

		ColumnarFileInfo cInfo1 = new  ColumnarFileInfo(columnarFileName1+".hdr");
		s=new Columnarfile(columnarFileName1, 4, types);
		cInfo1 = s.getColumnarFileInfo(columnarFileName1+".hdr");
		colNames1 = cInfo1.getColumnNames();
		s.setColumnNames(colNames1);

		ColumnarBitmapEquiJoins.parseValue(valueConstraint);

		for(String str: colNames)
		{
			if(str.equalsIgnoreCase(columnName))
				break;
			columnAbsoluteIndex++;
		}


		for(String str: colNames1)
		{
			if(str.equalsIgnoreCase(columnName1))
				break;
			columnAbsoluteIndex1++;
		}
		
			try 
			{
				Heapfile reqHFile=f.getHeapfileForColumname(columnName);
				Heapfile reqHFile1=s.getHeapfileForColumname(columnName1);
				ArrayList <String> values=new ArrayList<String>();
				Scan ss=reqHFile.openScan();
				Tuple tt=new Tuple();
				RID temprrid=new RID();
				while((tt=ss.getNext(temprrid))!=null)
				{
					if(value instanceof StringKey)
					{
						if(values.contains(Convert.getStrValue(0, tt.getData(), Size.STRINGSIZE))==false)
						{
							//System.out.println("testing1: "+Convert.getStrValue(0, tt.getData(), Size.STRINGSIZE));
							values.add(Convert.getStrValue(0, tt.getData(), Size.STRINGSIZE));
						}
					}
					else
					{
						if(values.contains(String.valueOf(Convert.getIntValue(0, tt.getData())))==false)
						{
							//System.out.println("testing2: "+Convert.getIntValue(0, tt.getData()));
							values.add(String.valueOf(Convert.getIntValue(0, tt.getData())));
						}
					}
				}
				
				while(values.isEmpty()!=true)
				{
					
					columnValue=values.get(0);
					try  
				    {  
				       intValue=Integer.parseInt( columnValue );  
				       value=InstantiateColumnarFile.setKeyClass(value, 0, columnValue);
				    }  
				    catch( Exception e)  
				    {  
				    	value=InstantiateColumnarFile.setKeyClass(value, 1, columnValue);
				    } 
					String bmfName="bitmap."+columnName+columnValue+columnarFileName;
					bmf=InstantiateColumnarFile.getColumnarFile(bmf, f, value, columnIndex,bmfName, reqHFile);				

					columnValue1=columnValue;
					String bmfName1="bitmap."+columnName1+columnValue1+columnarFileName1;
					bmf1=InstantiateColumnarFile.getColumnarFile(bmf1, s, value, columnIndex1,bmfName1, reqHFile1);				
					
					BitMapFile.bitwiseANDBitmaps(bmf, bmf1, reqHFile, reqHFile1,resBf,columnNames,columnNames1, value, intValue,columnValue);
					
					columnValue1=columnValue;
					try  
				    {  
				       value=InstantiateColumnarFile.setKeyClass(value, 0, columnValue);
				    }  
				    catch( Exception e)  
				    {  
				    	value=InstantiateColumnarFile.setKeyClass(value, 1, columnValue);
				    }
				    
				    //System.out.println("colval: "+columnValue);
				    values.remove(0);
				}
				
				while(columnNames.isEmpty()!=true)
					columnNames.remove(0);
				
				while(columnNames1.isEmpty()!=true)
					columnNames1.remove(0);

				System.out.println("Disk Reads"+ (pcounter.rcounter - startRead));
				System.out.println("Disk Writes"+ (pcounter.wcounter - startWrite));
			} catch (Exception e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
					

		try {
		SystemDefs.JavabaseBM.resetAllPinCount();
		SystemDefs.JavabaseBM.flushAllPages();
		SystemDefs.JavabaseDB.closeDB();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	public static TID getProjectionLeft(int position) throws InvalidSlotNumberException, HFException, HFDiskMgrException, HFBufMgrException, Exception
	{
		int colSize = columnNames.size();
		ArrayList<Tuple> arrTuples=new ArrayList<Tuple>();
		RID rid = new RID();
		Heapfile hf;
		Tuple t;
		TID tid=new TID(colSize);
		tid.recordIDs=new RID[colSize];
		tid.pos=position;
		tid.numRIDs=colSize;
		System.out.print("[");
		for(int j=0;j<colSize;j++)
			tid.recordIDs[j]=new RID();

		System.out.print("[");
		for (int i = 0 ; i < colSize ; i++)
		{
			hf = f.getHeapfileForColumname(columnNames.get(i).toString());
			rid = hf.PosToRid(position);
			t = hf.getRecord(rid);
			tid.recordIDs[i]=rid;
			if(t.getLength()>4)
				System.out.print(Convert.getStrValue(0, t.getData(), t.getLength())+", ");
			else
				System.out.print(Convert.getIntValue(0, t.getData())+", ");
			arrTuples.add(hf.getRecord(rid));
		}
		System.out.println("]");
		return tid;
	}
	
	public static TID getProjectionRight(int position) throws InvalidSlotNumberException, HFException, HFDiskMgrException, HFBufMgrException, Exception
	{
		int colSize = columnNames1.size();
		ArrayList<Tuple> arrTuples=new ArrayList<Tuple>();
		RID rid = new RID();
		Heapfile hf;
		Tuple t;
		TID tid=new TID(colSize);
		tid.recordIDs=new RID[colSize];
		tid.pos=position;
		tid.numRIDs=colSize;
		System.out.print("[");
		for(int j=0;j<colSize;j++)
			tid.recordIDs[j]=new RID();

		System.out.print("[");
		for (int i = 0 ; i < colSize ; i++)
		{
			hf = s.getHeapfileForColumname(columnNames1.get(i).toString());
			rid = hf.PosToRid(position);
			t = hf.getRecord(rid);
			tid.recordIDs[i]=rid;
			if(t.getLength()>4)
				System.out.print(Convert.getStrValue(0, t.getData(), t.getLength())+", ");
			else
				System.out.print(Convert.getIntValue(0, t.getData())+", ");
			arrTuples.add(hf.getRecord(rid));
		}
		System.out.println("]");
		return tid;
	}
	
}